package com.heantai.easystruts.controller;


import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.xmlrules.DigesterLoader;

import com.heantai.easystruts.config.ActionBean;
import com.heantai.easystruts.config.ActionFormBean;
import com.heantai.easystruts.config.ActionFormsBean;
import com.heantai.easystruts.config.ActionMappingsBean;
import com.heantai.easystruts.config.ForwardBean;
import com.heantai.easystruts.config.StrutsConfigBean;
import com.heantai.easystruts.form.ActionForm;

/**
 * 将表单中的数据封装到一个ActionForm对象里， 然后，再将ActionForm对象存放到request/ session。
 */
public class ActionServlet extends HttpServlet {
	private ActionMappingsBean amb;//可以删除也可保留，此方法为保留，减少对源代码的影响
	private StrutsConfigBean configBean;
	@Override
	protected void service(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HttpSession session=request.getSession();
		Locale locale = (Locale) session.getAttribute("locale");
		System.out.println("1231321");
//		System.out.println(locale.getDisplayName());
		Map<String, String> map=null;
		if(locale==null){
			System.out.println("54");
			Locale localeOfReq =request.getLocale();
			session.setAttribute("locale", localeOfReq);
			map = (Map<String, String>) getServletContext().getAttribute(localeOfReq.getDisplayName());
			if(map==null){
				System.out.println("mappppp");
				map=init_resource(localeOfReq);
			}
		}else{
			Locale localeOfReq =request.getLocale();
			map = (Map<String, String>) getServletContext().getAttribute(localeOfReq.getDisplayName());
		}
		
		String path = getPath(request);
		//查询配置文件
		ActionBean actionBean=amb.findActionBean(path);
		try {
			Action action = getActionBean(actionBean);
			//将表单中的数据放到ActionForm
			ActionForm actionForm = proccessActionForm(request, actionBean);
			//调用action
			action.setMap(map);
			String rs=action.execute(actionForm,request, response);
			// 依据Action执行之后返回的逻辑路径进行跳转。
			goForward(request, response, actionBean, rs);
		} catch (Exception e) {
			e.printStackTrace();
			throw new ServletException(e);
		}
	}
	/**54
	 * 将表单中的数据放到ActionForm
	 */
	private ActionForm proccessActionForm(HttpServletRequest request,
			ActionBean actionBean) throws Exception {
		ActionForm actionForm=null;
		String name=actionBean.getName();
		if(name!=null){
			String attribute = actionBean.getAttribute();
			String scope=actionBean.getScope();
			//先查看scope所指定的范围里有没有attribute所对应的对象，如果没有，则创建ActionForm实例,并且，将ActionForm实例存放到scope所指定的范围。
			if("request".equals(scope)){
				actionForm=(ActionForm) request.getAttribute(attribute);
			}else{
				actionForm=(ActionForm) request.getSession().getAttribute(attribute);
			}
			ActionFormsBean actionFormsBean=configBean.getActionFormsBean();
			ActionFormBean actionFormBean=actionFormsBean.findActionFormBean(name);
			String type=actionFormBean.getType();
			actionForm =(ActionForm)Class.forName(type).newInstance();
			Map map = request.getParameterMap();
			// 将表单中的数据copy to actionForm里
			BeanUtils.populate(actionForm, map);
			if (scope.equals("request")) {
				request.setAttribute(attribute, actionForm);
			} else {
				request.getSession().setAttribute(attribute, actionForm);
			}
		}
		return actionForm;
	}
	/**
	 * 依据action执行之后返回的逻辑路径执行跳转
	 */
	private void goForward(HttpServletRequest request,
			HttpServletResponse response, ActionBean actionBean, String rs)
			throws IOException, ServletException {
		ForwardBean forwardBean=actionBean.findForwardBean(rs);
		if(forwardBean.isRedirect()){
			response.sendRedirect(request.getContextPath()+forwardBean.getPath());//绝对路径
		}else{
			request.getRequestDispatcher(forwardBean.getPath()).forward(request, response);//绝对路径
		}
	}
	/**
	 * 依据配置文件找到对应的actionbean并创建实例
	 * @param actionBean
	 * @return
	 * @throws Exception
	 */
	private Action getActionBean(ActionBean actionBean)
			throws Exception {
		String type=actionBean.getType();
		Action action=(Action) Class.forName(type).newInstance();
		return action;
	}
	/**
	 * 分析请求
	 * @param request
	 * @return
	 */
	private String getPath(HttpServletRequest request) {
		String uri =request.getRequestURI();
		String path=uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
		return path;
	}
	@Override
	public void init() throws ServletException {
		init_config();
		init_resource(Locale.getDefault());
	}
	/**
	 * 依据locale信息加载对应的资源文件到内存
	 */
	private Map<String, String> init_resource(Locale locale) {
		System.out.println(locale);
		System.out.println(configBean.getRb().getParameter());
		ResourceBundle rb=ResourceBundle.getBundle(configBean.getRb().getParameter(),locale);
		Enumeration<String> keys=rb.getKeys();
		Map<String, String> map=new HashMap<String, String>();
		while(keys.hasMoreElements()){
			String key=keys.nextElement();
			String value=rb.getString(key);
			map.put(key, value);
		}
		System.out.println(locale.getDisplayName()+",init");
		getServletContext().setAttribute(locale.getDisplayName(), map);
		System.out.println(getServletContext().getAttribute(locale.getDisplayName())+",init");
		return map;
	}
	/**
	 * @throws ServletException
	 */
	private void init_config() throws ServletException {
		Digester digester=DigesterLoader.createDigester(ActionServlet.class.getResource("/com/heantai/easystruts/config/rule.xml"));
//		Digester digester=DigesterLoader.createDigester(ActionServlet.class.getClassLoader().getResource("com/heantai/easystruts/config/rule.xml"));
		configBean= new StrutsConfigBean();
		digester.push(configBean);
		try {
			digester.parse(ActionServlet.class.getResourceAsStream("/easystruts-config.xml"));
		} catch (Exception e) {
			e.printStackTrace();
			throw new ServletException(e);
		} 
		//给amb赋值，使ActionBean actionBean=amb.findActionBean(path);可用
		amb=configBean.getActionMappingsBean();
	}
}
